const MapKeys = require('../template')

console.log("=== MapKeys 复杂场景测试 ===")

// 测试多层循环引用映射键
console.log(
  "多层循环引用映射键:", (() => {
    const obj1 = { id: 1, name: 'obj1' }
    const obj2 = { id: 2, name: 'obj2' }
    const obj3 = { id: 3, name: 'obj3' }

    obj1.ref = obj2
    obj2.ref = obj3
    obj3.ref = obj1

    const mapped = MapKeys.mapKeys(obj1, (value, key) => key.toUpperCase())

    return typeof mapped === 'object' &&
      mapped.ID === 1 &&
      mapped.NAME === 'obj1' &&
      mapped.REF === obj2 &&
      !('id' in mapped) &&
      !('name' in mapped) &&
      !('ref' in mapped)
  })()
)

// 测试混合类型复杂结构映射键
console.log(
  "混合类型复杂结构映射键:", (() => {
    const obj = {
      string: 'test',
      number: 42,
      boolean: true,
      null: null,
      undefined: undefined,
      array: [1, 'two', { three: 3 }],
      object: { nested: { deep: 'value' } },
      date: new Date('2023-01-01'),
      regex: /test/gi,
      function: function test() { return 'hello' },
      symbol: Symbol('test'),
      bigint: BigInt(123),
      map: new Map([['a', 1], ['b', 2]]),
      set: new Set([1, 2, 3]),
      typedArray: new Uint8Array([1, 2, 3]),
      arrayBuffer: new ArrayBuffer(8),
      dataView: new DataView(new ArrayBuffer(8)),
      error: new Error('test error')
    }

    const mapped = MapKeys.mapKeys(obj, (value, key) => key.toUpperCase())

    return typeof mapped === 'object' &&
      mapped.STRING === 'test' &&
      mapped.NUMBER === 42 &&
      mapped.BOOLEAN === true &&
      mapped.NULL === null &&
      mapped.UNDEFINED === undefined &&
      mapped.ARRAY === obj.array &&
      mapped.OBJECT === obj.object &&
      mapped.DATE === obj.date &&
      mapped.REGEX === obj.regex &&
      mapped.FUNCTION === obj.function &&
      mapped.SYMBOL === obj.symbol &&
      mapped.BIGINT === obj.bigint &&
      mapped.MAP === obj.map &&
      mapped.SET === obj.set &&
      mapped.TYPEDARRAY === obj.typedArray &&
      mapped.ARRAYBUFFER === obj.arrayBuffer &&
      mapped.DATAVIEW === obj.dataView &&
      mapped.ERROR === obj.error &&
      !('string' in mapped) &&
      !('number' in mapped) &&
      !('boolean' in mapped) &&
      !('null' in mapped) &&
      !('undefined' in mapped) &&
      !('array' in mapped) &&
      !('object' in mapped) &&
      !('date' in mapped) &&
      !('regex' in mapped) &&
      !('function' in mapped) &&
      !('symbol' in mapped) &&
      !('bigint' in mapped) &&
      !('map' in mapped) &&
      !('set' in mapped) &&
      !('typedArray' in mapped) &&
      !('arrayBuffer' in mapped) &&
      !('dataView' in mapped) &&
      !('error' in mapped)
  })()
)

// 测试深度嵌套数组映射键
console.log(
  "深度嵌套数组映射键:", (() => {
    let arr = [1, 2, 3]
    for (let i = 0; i < 10; i++) {
      arr = [arr, { level: i, data: `level${i}` }]
    }

    const obj = { arr, data: 'test' }
    const mapped = MapKeys.mapKeys(obj, (value, key) => key.toUpperCase())

    return typeof mapped === 'object' &&
      mapped.ARR === arr &&
      mapped.DATA === 'test' &&
      !('arr' in mapped) &&
      !('data' in mapped)
  })()
)

// 测试原型链继承映射键
console.log(
  "原型链继承映射键:", (() => {
    function BaseClass() {
      this.baseProp = 'base'
    }
    BaseClass.prototype.baseMethod = function() { return 'base method' }

    function DerivedClass() {
      BaseClass.call(this)
      this.derivedProp = 'derived'
    }
    DerivedClass.prototype = Object.create(BaseClass.prototype)
    DerivedClass.prototype.constructor = DerivedClass
    DerivedClass.prototype.derivedMethod = function() { return 'derived method' }

    const instance = new DerivedClass()
    const mapped = MapKeys.mapKeys(instance, (value, key) => key.toUpperCase())

    return typeof mapped === 'object' &&
      mapped.BASEPROP === 'base' &&
      mapped.DERIVEDPROP === 'derived' &&
      !('baseProp' in mapped) &&
      !('derivedProp' in mapped)
  })()
)

// 测试自定义类实例映射键
console.log(
  "自定义类实例映射键:", (() => {
    class CustomClass {
      constructor(value) {
        this.value = value
        this.timestamp = new Date()
      }

      getValue() {
        return this.value
      }

      setValue(newValue) {
        this.value = newValue
      }
    }

    const instance = new CustomClass('test')
    const mapped = MapKeys.mapKeys(instance, (value, key) => key.toUpperCase())

    return typeof mapped === 'object' &&
      mapped.VALUE === 'test' &&
      mapped.TIMESTAMP === instance.timestamp &&
      !('value' in mapped) &&
      !('timestamp' in mapped)
  })()
)

// 测试稀疏数组映射键
console.log(
  "稀疏数组映射键:", (() => {
    const arr = new Array(1000)
    arr[0] = 'first'
    arr[999] = 'last'
    arr[500] = 'middle'

    const obj = { arr, data: 'test' }
    const mapped = MapKeys.mapKeys(obj, (value, key) => key.toUpperCase())

    return typeof mapped === 'object' &&
      mapped.ARR === arr &&
      mapped.DATA === 'test' &&
      !('arr' in mapped) &&
      !('data' in mapped)
  })()
)

// 测试TypedArray嵌套映射键
console.log(
  "TypedArray嵌套映射键:", (() => {
    const obj = {
      uint8Array: new Uint8Array([1, 2, 3]),
      int16Array: new Int16Array([100, 200, 300]),
      float32Array: new Float32Array([1.1, 2.2, 3.3]),
      nested: {
        uint32Array: new Uint32Array([1000, 2000, 3000]),
        int8Array: new Int8Array([-1, -2, -3])
      }
    }

    const mapped = MapKeys.mapKeys(obj, (value, key) => key.toUpperCase())

    return typeof mapped === 'object' &&
      mapped.UINT8ARRAY === obj.uint8Array &&
      mapped.INT16ARRAY === obj.int16Array &&
      mapped.FLOAT32ARRAY === obj.float32Array &&
      mapped.NESTED === obj.nested &&
      !('uint8Array' in mapped) &&
      !('int16Array' in mapped) &&
      !('float32Array' in mapped) &&
      !('nested' in mapped)
  })()
)

// 测试Map和Set嵌套映射键
console.log(
  "Map和Set嵌套映射键:", (() => {
    const map1 = new Map([['a', 1], ['b', 2]])
    const map2 = new Map([['c', 3], ['d', 4]])
    const set1 = new Set([1, 2, 3])
    const set2 = new Set([4, 5, 6])

    const obj = {
      maps: { map1, map2 },
      sets: { set1, set2 },
      nested: {
        map: new Map([['nested', 'value']]),
        set: new Set(['nested'])
      }
    }

    const mapped = MapKeys.mapKeys(obj, (value, key) => key.toUpperCase())

    return typeof mapped === 'object' &&
      mapped.MAPS === obj.maps &&
      mapped.SETS === obj.sets &&
      mapped.NESTED === obj.nested &&
      !('maps' in mapped) &&
      !('sets' in mapped) &&
      !('nested' in mapped)
  })()
)

// 测试Error对象嵌套映射键
console.log(
  "Error对象嵌套映射键:", (() => {
    const error1 = new Error('First error')
    error1.code = 'ERR_001'
    error1.details = { line: 10, column: 5 }

    const error2 = new TypeError('Second error')
    error2.code = 'ERR_002'
    error2.stack = 'TypeError: Second error\n    at test.js:15:10'

    const obj = {
      errors: [error1, error2],
      nested: {
        error: new ReferenceError('Third error'),
        data: { message: 'test' }
      }
    }

    const mapped = MapKeys.mapKeys(obj, (value, key) => key.toUpperCase())

    return typeof mapped === 'object' &&
      mapped.ERRORS === obj.errors &&
      mapped.NESTED === obj.nested &&
      !('errors' in mapped) &&
      !('nested' in mapped)
  })()
)

// 测试Date对象嵌套映射键
console.log(
  "Date对象嵌套映射键:", (() => {
    const date1 = new Date('2023-01-01')
    const date2 = new Date('2023-12-31')
    const date3 = new Date('2023-06-15')

    const obj = {
      dates: [date1, date2, date3],
      nested: {
        created: date1,
        updated: date2,
        metadata: {
          timestamp: date3,
          data: 'test'
        }
      }
    }

    const mapped = MapKeys.mapKeys(obj, (value, key) => key.toUpperCase())

    return typeof mapped === 'object' &&
      mapped.DATES === obj.dates &&
      mapped.NESTED === obj.nested &&
      !('dates' in mapped) &&
      !('nested' in mapped)
  })()
)

// 测试RegExp对象嵌套映射键
console.log(
  "RegExp对象嵌套映射键:", (() => {
    const regex1 = /test/gi
    const regex2 = /pattern/im
    const regex3 = /example/gu

    const obj = {
      patterns: [regex1, regex2, regex3],
      nested: {
        email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
        phone: /^\+?[\d\s-()]+$/,
        config: {
          url: /^https?:\/\/.+/,
          data: 'test'
        }
      }
    }

    const mapped = MapKeys.mapKeys(obj, (value, key) => key.toUpperCase())

    return typeof mapped === 'object' &&
      mapped.PATTERNS === obj.patterns &&
      mapped.NESTED === obj.nested &&
      !('patterns' in mapped) &&
      !('nested' in mapped)
  })()
)

// 测试Symbol对象嵌套映射键
console.log(
  "Symbol对象嵌套映射键:", (() => {
    const sym1 = Symbol('test1')
    const sym2 = Symbol('test2')
    const sym3 = Symbol('test3')

    const obj = {
      symbols: [sym1, sym2, sym3],
      nested: {
        key1: sym1,
        key2: sym2,
        config: {
          key3: sym3,
          data: 'test'
        }
      }
    }

    const mapped = MapKeys.mapKeys(obj, (value, key) => key.toUpperCase())

    return typeof mapped === 'object' &&
      mapped.SYMBOLS === obj.symbols &&
      mapped.NESTED === obj.nested &&
      !('symbols' in mapped) &&
      !('nested' in mapped)
  })()
)

// 测试BigInt对象嵌套映射键
console.log(
  "BigInt对象嵌套映射键:", (() => {
    const big1 = BigInt(123)
    const big2 = BigInt(456)
    const big3 = BigInt(789)

    const obj = {
      bigints: [big1, big2, big3],
      nested: {
        value1: big1,
        value2: big2,
        config: {
          value3: big3,
          data: 'test'
        }
      }
    }

    const mapped = MapKeys.mapKeys(obj, (value, key) => key.toUpperCase())

    return typeof mapped === 'object' &&
      mapped.BIGINTS === obj.bigints &&
      mapped.NESTED === obj.nested &&
      !('bigints' in mapped) &&
      !('nested' in mapped)
  })()
)

// 测试边界情况映射键
console.log(
  "边界情况映射键:", (() => {
    const obj = { '': 'empty key', ' ': 'space key', 'a': 'normal key' }
    const mapped = MapKeys.mapKeys(obj, (value, key) => key === '' ? 'empty' : `key_${key}`)

    return typeof mapped === 'object' &&
      mapped.empty === 'empty key' &&
      mapped.key_space === 'space key' &&
      mapped.key_a === 'normal key' &&
      !('' in mapped) &&
      !(' ' in mapped) &&
      !('a' in mapped)
  })()
)

// 测试特殊字符映射键
console.log(
  "特殊字符映射键:", (() => {
    const obj = { 'key-with-dash': 'value1', 'key.with.dot': 'value2' }
    const mapped = MapKeys.mapKeys(obj, (value, key) => key.replace(/[-.]/g, '_'))

    return typeof mapped === 'object' &&
      mapped.key_with_dash === 'value1' &&
      mapped.key_with_dot === 'value2' &&
      !('key-with-dash' in mapped) &&
      !('key.with.dot' in mapped)
  })()
)

// 测试数字键映射键
console.log(
  "数字键映射键:", (() => {
    const obj = { 0: 'zero', 1: 'one', 2: 'two' }
    const mapped = MapKeys.mapKeys(obj, (value, key) => `num_${key}`)

    return typeof mapped === 'object' &&
      mapped.num_0 === 'zero' &&
      mapped.num_1 === 'one' &&
      mapped.num_2 === 'two' &&
      !('0' in mapped) &&
      !('1' in mapped) &&
      !('2' in mapped)
  })()
)

// 测试布尔值键映射键
console.log(
  "布尔值键映射键:", (() => {
    const obj = { true: 'yes', false: 'no' }
    const mapped = MapKeys.mapKeys(obj, (value, key) => `is_${key}`)

    return typeof mapped === 'object' &&
      mapped.is_true === 'yes' &&
      mapped.is_false === 'no' &&
      !('true' in mapped) &&
      !('false' in mapped)
  })()
)

// 测试重复键映射键
console.log(
  "重复键映射键:", (() => {
    const obj = { a: 1, b: 2, c: 3 }
    const mapped = MapKeys.mapKeys(obj, (value, key) => 'same')

    return typeof mapped === 'object' &&
      mapped.same === 3 && // 最后一个值会覆盖前面的
      Object.keys(mapped).length === 1
  })()
)

console.log("=== MapKeys 复杂场景测试完成 ===")
